package com.nengchuan.eic.nceconomy.service;

import com.nengchuan.eic.nceconomy.component.template.ResponseModel;
import com.nengchuan.eic.nceconomy.constant.CommonConstant;
import com.nengchuan.eic.nceconomy.constant.SheetDataEnum;
import com.nengchuan.eic.nceconomy.constant.SheetEnum;
import com.nengchuan.eic.nceconomy.constant.SheetFormatEnum;
import com.nengchuan.eic.nceconomy.dao.TemplateFileMapper;
import com.nengchuan.eic.nceconomy.dao.TemplateSheetMapper;
import com.nengchuan.eic.nceconomy.entity.po.*;
import com.nengchuan.eic.nceconomy.dao.TemplateDicMapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.nengchuan.eic.nceconomy.entity.vo.*;
import com.nengchuan.eic.nceconomy.util.ExcelSerialNumUtils;
import com.nengchuan.model.model.WrappedResult;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 模板字典表 服务实现类
 * </p>
 *
 * @author luoping
 * @since 2020-04-23
 */
@Service
public class TemplateDicServiceImpl extends ServiceImpl<TemplateDicMapper, TemplateDic> implements TemplateDicService {
    @Autowired
    private TemplateDicMapper templateDicMapper;

    @Autowired
    private TemplateSheetMapper templateSheetMapper;

    @Autowired
    private TemplateFileMapper templateFileMapper;

    @Autowired
    private OssService ossService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public int save(List<ResponseModel> templateResponses, TemplateFile templateFile) {


        templateFileMapper.insert(templateFile);

        ResponseModel templateResponse;
        for (int i = 0; i < templateResponses.size(); i++) {
            templateResponse = templateResponses.get(i);

            templateResponse.getTemplateSheet();
            List<TemplateDic> templateDics = templateResponse.getTemplateDics();
            TemplateSheet sheet = templateResponse.getTemplateSheet();
            sheet.setTemplateFileId(templateFile.getId());
            templateSheetMapper.insert(sheet);

            templateDics.forEach(e -> {
                e.setSheetId(sheet.getId());
                e.setTemplateFileId(templateFile.getId());
            });
            templateDicMapper.insertList(templateDics);

        }
        return 0;

    }

    /**
     * 获取模板信息
     *
     * @param categoryIndex
     * @param projectIndex
     */
    @Override
    public SheetDetail getTemplate(String categoryIndex, String projectIndex, Long sheetId) {
        //获取excel模板对应的模板阶段及表名
        SheetInfoVO sheetInfoVO = templateFileMapper.getSheetInfo(categoryIndex, projectIndex, sheetId);
        if (sheetInfoVO == null) {
            return null;
        }
        //获取全部数据
        boolean fold = SheetFormatEnum.isFold(sheetInfoVO.getTemplateSheetName());
        List<TemplateDic> templateData=null;
        if (fold) {
            templateData = templateFileMapper.selectSheetDetailOnParentNode(sheetInfoVO.getTemplateId(), sheetInfoVO.getSheetId());
        } else {
            templateData=templateFileMapper.getTemplate(sheetInfoVO.getTemplateId(), sheetInfoVO.getSheetId());
        }
        if (templateData == null) {
            return null;
        }
        TreeMap<Integer, List<TemplateDic>> collect = templateData.stream().collect(Collectors.groupingBy(TemplateDic::getLineStartCoordinates, TreeMap::new, Collectors.toList()));
        //检查是否有多级表头
        SheetDataEnum sheetDataEnum = SheetDataEnum.getHeadlineNumByTemplateSheetName(sheetInfoVO.getTemplateSheetName());
        int keyNum = collect.get(sheetDataEnum.getLineStartCoordinates()).size();
        List<HeadLineVO> headLineList = headLine(collect, sheetDataEnum);
        //标题
        List<TemplateDic> title = collect.remove(SheetDataEnum.getTitleLineNumByTemplateSheetName(sheetInfoVO.getTemplateSheetName()));
        //获取表头
        List<TemplateDic> tableHead = collect.remove(SheetDataEnum.getTableheadLineNumByTemplateSheetName(sheetInfoVO.getTemplateSheetName()));
        List<HeadLineVO> tableHeadList = new ArrayList<>();
        for (TemplateDic aTableHead : tableHead) {
            HeadLineVO headLineVO = new HeadLineVO();
            headLineVO.setKey(aTableHead.getValue());
            tableHeadList.add(headLineVO);
        }
        //获取表内容 （行）
        List<Map<String, Object>> content = new ArrayList<>();
        lineContent(collect, content, keyNum,sheetInfoVO.getSheetId(),fold);
        return new SheetDetail(sheetInfoVO.getExcelName(), sheetInfoVO.getTemplateSheetName(), tableHeadList, headLineList, content);
    }

    /**
     * 获取模板sheetList
     *
     * @param categoryIndex
     * @param projectIndex
     */
    @Override
    public ExcelSheetListVO getTemplateSheetList(String categoryIndex, String projectIndex) {
        ExcelSheetListVO listVO = new ExcelSheetListVO();
        List<SheetVO> list = templateFileMapper.selectSheetList(categoryIndex, projectIndex);
        list.forEach(x -> {
            x.setFold(SheetFormatEnum.isFold(x.getSheetTemplateName()));
            listVO.getImportanceSheet().add(x);
            listVO.setTemplateId(x.getId());
        });
        return listVO;
    }


    /**
     * 获取表头
     *
     * @param map           数据
     * @param sheetDataEnum 表头开始行
     * @return 表头
     */
    private List<HeadLineVO> headLine(Map<Integer, List<TemplateDic>> map, SheetDataEnum sheetDataEnum) {
        List<HeadLineVO> headLineList = new ArrayList<>();
        if (!sheetDataEnum.getLineStartCoordinates().equals(sheetDataEnum.getLineEndCoordinates())) {
            //存在多级标题
            List<TemplateDic> headLine = map.remove(sheetDataEnum.getLineStartCoordinates());
            for (int i = 0; i < headLine.size(); i++) {
                HeadLineVO headLineVO = new HeadLineVO();
                String value = headLine.get(i).getValue();
                if (value.contains("-")) {
                    String[] split = value.split("-");
                    StringBuilder sb = new StringBuilder();
                    for (int j = 0; j < split.length; j++) {
                        HeadLineVO vo = new HeadLineVO();
                        sb.append(split[j]);
                        vo.setKey(sb.toString());
                        if (j == split.length - 1) {
                            if(!SheetFormatEnum.isExist(value)){
                                vo.setFormat("1");
                            }
                            vo.setKey(value);
                            vo.setValue("key" + i);
                        } else {
                            vo.setTitleChildren(new ArrayList<>());
                            sb.append("-");
                        }
                        if (headLineList.stream().noneMatch(x -> vo.getKey().equals(x.getKey()))) {
                            headLineList.add(vo);
                        }
                    }
                } else {
                    if(!SheetFormatEnum.isExist(value)){
                        headLineVO.setFormat("1");
                    }
                    headLineVO.setKey(value);
                    headLineVO.setValue("key" + i);
                    headLineList.add(headLineVO);
                }
            }
            List<HeadLineVO> collect = headLineList.stream().filter(x -> x.getKey().contains("-")).collect(Collectors.toList());
            List<HeadLineVO> result = headLineList.stream().filter(x -> !x.getKey().contains("-")).collect(Collectors.toList());
            //生成多级标题
            getMultilevelTitle(collect, result);
            wipeOffSymbol(result);
            headLineList = result;

        } else {
            List<TemplateDic> headLine = map.remove(sheetDataEnum.getLineStartCoordinates());
            for (int i = 0; i < headLine.size(); i++) {
                HeadLineVO headLineVO = new HeadLineVO();
                if(!SheetFormatEnum.isExist(headLine.get(i).getValue())){
                    headLineVO.setFormat("1");
                }
                headLineVO.setKey(headLine.get(i).getValue());
                headLineVO.setValue("key" + i);
                headLineList.add(headLineVO);
            }
        }
        return headLineList;
    }

    /**
     * 获取多级标题
     *
     * @param containCollet   包含-的标题
     * @param noContainCollet 不包含-的标题
     */
    private void getMultilevelTitle(List<HeadLineVO> containCollet, List<HeadLineVO> noContainCollet) {
        if (containCollet.size() == 0) {
            return;
        }
        List<HeadLineVO> collect = new ArrayList<>();
        noContainCollet.forEach(x -> {
            containCollet.forEach(y -> {
                if (y.getKey().startsWith(x.getKey())) {
                    String replace = y.getKey().replace(x.getKey(), "");
                    if (!replace.substring(1).contains("-")) {
                        x.getTitleChildren().add(y);
                        collect.add(y);
                    }
                }
            });
        });
        containCollet.removeAll(collect);
        getMultilevelTitle(containCollet, collect);
    }


    /**
     * 将结果集中的-去掉
     *
     * @param result
     */
    private void wipeOffSymbol(List<HeadLineVO> result) {
        result.forEach(x -> {
            if (x.getKey().contains("-")) {
                String[] split = x.getKey().split("-");
                x.setKey(split[split.length - 1]);
            }
            List<HeadLineVO> titleChildren = x.getTitleChildren();
            if (titleChildren != null) {
                titleChildren.forEach(y -> {
                    if (y.getKey().contains("-")) {
                        String[] split = y.getKey().split("-");
                        y.setKey(split[split.length - 1]);
                    }
                    if (y.getTitleChildren() != null && y.getTitleChildren().size() > 0) {
                        wipeOffSymbol(y.getTitleChildren());
                    }
                });
            }
        });
    }

    /**
     * 获取行
     *
     * @param map     数据
     * @param content 内容
     */
    private void lineContent(Map<Integer, List<TemplateDic>> map, List<Map<String, Object>> content, int keyNum,Long templateId,boolean fold) {
        Long parentId = null;
        boolean intoContent = false;
        TemplateSheet templateSheet = templateSheetMapper.judgeSheetByIdIsFisrt(templateId);
        for (Map.Entry<Integer, List<TemplateDic>> entry : map.entrySet()) {
            List<TemplateDic> value = entry.getValue();
            Map<String, Object> map1 = new HashMap<>();
            map1.put("id", value.get(0).getId());
            boolean isIntoParent = false;
            for (int i = 0; i < value.size(); i++) {
                TemplateDic templateDic = value.get(i);
                if (templateSheet == null) {
                    if (value.get(0).getParentId() != null) {
                        intoContent = false;
                        value.get(i).setParentId(value.get(0).getParentId());
                    } else {
                        intoContent = true;
                    }

                    if (value.get(0).getParentId() == null) {
                        parentId = templateDic.getId();
                    } else if (!value.get(0).getParentId().equals(parentId)) {
                        parentId = templateDic.getParentId();
                    } else {
                        if (!isIntoParent) {
                            searchAndIntoParent(content, parentId, map1);
                        }
                        isIntoParent = true;
                    }
                    if (StringUtils.isNotBlank(templateDic.getUnit())) {
                        map1.put("key" + i, templateDic.getValue() + "  " + templateDic.getUnit());
                    } else {
                        map1.put("key" + i, templateDic.getValue());
                    }
                } else {
                    intoContent=true;
                    map1.put("key" + i, templateDic.getValue());
                }
            }
            if (map1.keySet().size() < keyNum) {
                for (int i = map1.keySet().size() + 1; i < keyNum; i++) {
                    map1.put("key" + i, "");
                }
            }

            if (intoContent) {
                if (fold) {
                    Object key0 = map1.get("key0");
                    if (ExcelSerialNumUtils.isUpperSeq((String) key0)) {
                        map1.put("hasChildren", fold);
                    }
                }
                content.add(map1);
            }
        }
    }
    /**
     * 根据父id查询sheetList
     *
     * @param id
     * @return
     */
    @Override
    public List<Map<String, Object>> getSheetListByPid(Long id, Long sheetId) {
        List<TemplateDicHaveSon> originIndexData = templateDicMapper.getSheetListByPid(id, sheetId);
        List<Map<String, Object>> content=new ArrayList<>();
        TreeMap<Integer, List<TemplateDicHaveSon>> collect = originIndexData.stream().collect(Collectors.groupingBy(TemplateDicHaveSon::getLineStartCoordinates, TreeMap::new, Collectors.toList()));
        for (Map.Entry<Integer, List<TemplateDicHaveSon>> entry : collect.entrySet()) {
            List<TemplateDicHaveSon> value = entry.getValue();
            Map<String, Object> map1 = new HashMap<>();
            map1.put("id", value.get(0).getId());
            for (int i = 0; i < value.size(); i++) {
                TemplateDicHaveSon originIndexData1 = value.get(i);
                map1.put("key" + i, originIndexData1.getValue());
            }
            map1.put("hasChildren", value.get(0).getHaveSon() != null);
            content.add(map1);
        }
        return content;
    }

    @Override
    public String download(Long templateId) throws Exception{
        TemplateFile excelFile = templateFileMapper.selectById(templateId);
        if (excelFile == null) {
            return null;
        }
        WrappedResult<OssFileReseponseVO> filesFromOssById = ossService.getFilesFromOssById(excelFile.getOssId());
        if (filesFromOssById != null && filesFromOssById.getData() != null) {
            return filesFromOssById.getData().getUrl();
        }
        return null;
    }

    /**
     * 内容---将子信息放入父信息中
     *
     * @param content  结果集合
     * @param parentId 父节点id
     * @param map1     新生成的子信息
     */
    private void searchAndIntoParent(List<Map<String, Object>> content, Long parentId, Map<String, Object> map1) {
        for (Map<String, Object> c : content) {
            List<Map<String, Object>> children = (List<Map<String, Object>>) c.get("children");
            if (parentId.equals(Long.valueOf(c.get("id").toString()))) {
                if (children == null) {
                    children = new ArrayList<>();
                    children.add(map1);
                    c.put("children", children);
                } else {
                    children.add(map1);
                }
            } else if (children != null) {
                searchAndIntoParent(children, parentId, map1);
            }
        }
    }

}
